#include "EffectTemplatePCH.h"
#include "EffectManager.h"
#include "Effect.h"
#include "Pass.h"
#include "Technique.h"

Technique Technique::InvalidTechnique(NULL, NULL);

Technique::Technique( CGcontext context, CGtechnique technique )
: m_cgContext( context )
, m_cgTechnique( technique )
{
    // Validate the technique
    m_bIsValid = ( m_cgTechnique != NULL ) && ( cgValidateTechnique(m_cgTechnique) == CG_TRUE );
    if ( m_cgTechnique != NULL )
    {
        const char* techniqueName = cgGetTechniqueName(m_cgTechnique);
        if ( techniqueName != NULL )
        {
            m_TechniquName = techniqueName;
        }

        // Get all the passes for this technique
        CGpass pass = cgGetFirstPass( m_cgTechnique );
        while ( pass != NULL )
        {
            Pass* pPass = new Pass( m_cgContext, pass );
            m_Passes.push_back(pPass);

            // Add the pass to the name map for faster lookup
            m_PassesByName.insert( PassMap::value_type( pPass->GetPassName(), pPass ) );

            pass = cgGetNextPass( pass );
        }
    }
}

Technique::~Technique()
{
    Destroy();
}

void Technique::Destroy()
{
    // Delete all the passes
    PassList::iterator passIter = m_Passes.begin();
    while ( passIter != m_Passes.end() )
    {
        delete (*passIter);
        ++passIter;
    }
    m_Passes.clear();
    m_PassesByName.clear();

    m_bIsValid = false;
}

bool Technique::IsValid() const
{
    return m_bIsValid;
}

const std::string& Technique::GetTechniqueName() const
{
    return m_TechniquName;
}

Technique::PassList& Technique::GetPasses()
{
    return m_Passes;
}

Pass& Technique::GetPassByName( const std::string& passName )
{
    PassMap::iterator passIter = m_PassesByName.find( passName );
    if ( passIter != m_PassesByName.end() )
    {
        return *(passIter->second);
    }
    
    return Pass::InvalidPass;
}


bool Technique::BeginTechnique()
{
    // TODO: Should the technique be revalidated with cgValidateTechnique?
    // Will this cause the technique to be recompiled every time? Or only when it 
    // needs to be?
    m_bIsValid = ( m_cgTechnique != NULL ) && ( cgValidateTechnique( m_cgTechnique ) == CG_TRUE );
    return m_bIsValid;
}

void Technique::EndTechnique()
{
    // Apparently we don't need to do anything...
    // Just end the pass.
}